home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / 4th Dimension / Relate Selection Source < prev   
Text File  |  1993-12-20  |  6KB  |  166 lines

  1. Here are two approaches to the RelateSelection procedure, which
  2. generates a selection of records in a file based on a selection of
  3. records in a related file.  In v3 JOIN and PROJECT SELECTION replace
  4. this method, though it still has some advantages.
  5.  
  6.  
  7.  
  8. Procedure RelateSelection (enhanced)   5/20/91
  9. ______________________________________________
  10. This is an enhanced version of the recently uploaded RelateSelection. It's 
  11. a little faster overall, and uses arrays to speed up searches on large 
  12. base file selections.
  13.  
  14. This code will find the records in a file (SearchFile) which are related 
  15. to a selection of records in another file  (BaseFile). The files can be 
  16. related one to many, many to one or without drawn relations at all (this 
  17. last is great for creating small indexes (lookup files) for large files). 
  18. So far, when compiled, the code appears to be faster than any other method.
  19.  
  20. Regarding the array technique, be aware that it requires 4 bytes of RAM 
  21. for each record in the selection.
  22.  
  23. The progress messages are based on Tech Note No. 206, "Displaying a Custom 
  24. Progress Indicator".
  25. ______________________________________________
  26.  
  27.   `RelateSelection - enhanced
  28.   `Based on original code by Tony Ringsmuth 6/90
  29.   `Modified 5/91 by Bob Keleher 70451,510 - with contributions
  30.   `and suggestions by Lincoln Stoller and other members of the Acius Forum.
  31.  
  32.   `$1 = >>Search field
  33.   `$2 = >>Base field
  34.  
  35. C_POINTER($SearchFile;$BaseFile)
  36. C_LONGINT($Max;$i;$j;$BaseRecs;$LastJ)
  37. $SearchFile:=File(File($1))  `get pointer to file from field pointer
  38. $BaseFile:=File(File($2))
  39. $BaseRecs:=Records in selection($BaseFile>>)
  40. $Max:=256  `built searches don't like more than 256
  41. Case of 
  42.   : ($BaseRecs=0)
  43.     CREATE EMPTY SET($SearchFile>>;"Related")
  44.     USE SET("Related")
  45.     CLEAR SET("Related")
  46.   : ($BaseRecs<=$Max)
  47.       `Setup progress indicator here e.g. Progress($BaseRecs;"Your 
  48. message")
  49.     FIRST RECORD($BaseFile>>)
  50.     SEARCH($SearchFile>>;$1>>=$2>>;*)
  51.       `Progress(1) `update thermometer
  52.     For ($i;2;$BaseRecs)
  53.       NEXT RECORD($BaseFile>>)
  54.       SEARCH($SearchFile>>; | $1>>=$2>>;*)
  55.         `Progress(1) `update thermometer
  56.     End for 
  57.     SEARCH($SearchFile>>)
  58.       `Progress(0) `close progress indicator window
  59.   Else 
  60.       `Setup progress indicator here e.g. 
  61. Progress(($BaseRecs\$Max)+1;"Your message")
  62.     $LastJ:=(($BaseRecs\$Max)*$Max)+1  `value of $j at last outer loop
  63.     CREATE EMPTY SET($SearchFile>>;"Related")
  64.     If (Type($2>>)=8) | (Type($2>>)=9)  `integer or LongInt
  65.       ARRAY LONGINT(vLIntArray;0)
  66.       SELECTION TO ARRAY($2>>;vLIntArray)
  67.       For ($j;1;$BaseRecs;$Max)
  68.         SEARCH($SearchFile>>;$1>>=vLIntArray{$j};*)
  69.         If ($j=$LastJ)  `last outer loop
  70.           $Max:=$BaseRecs-$j+1
  71.         End if
  72.         For ($i;$j+1;$j-1+$Max)
  73.           SEARCH($SearchFile>>; | $1>>=vLintArray{$i};*)
  74.         End for 
  75.         SEARCH($SearchFile>>)
  76.         CREATE SET($SearchFile>>;"Relating")
  77.         UNION("Related";"Relating";"Related")
  78.           `Progress(1) `update thermometer
  79.       End for 
  80.       CLEAR VARIABLE(vLIntArray)
  81.     Else 
  82.       FIRST RECORD($BaseFile>>)
  83.       For ($j;1;$BaseRecs;$Max)
  84.         SEARCH($SearchFile>>;$1>>=$2>>;*)
  85.         If ($j=$LastJ)
  86.           $Max:=$BaseRecs-$j+1
  87.         End if 
  88.         For ($i;2;$Max)
  89.           NEXT RECORD($BaseFile>>)
  90.           SEARCH($SearchFile>>; | $1>>=$2>>;*)
  91.         End for 
  92.         SEARCH($SearchFile>>)
  93.         CREATE SET($SearchFile>>;"Relating")
  94.         UNION("Related";"Relating";"Related")
  95.         NEXT RECORD($BaseFile>>)
  96.           `Progress(1) `update thermometer
  97.       End for 
  98.     End if 
  99.     USE SET("Related")
  100.     CLEAR SET("Related")
  101.     CLEAR SET("Relating")
  102.       `Progress(0) `close progress indicator window
  103. End case 
  104.  
  105.  
  106.  
  107. Date: Thu, 3 Jun 1993 13:01:07 -0800
  108. From: chuckp@shiva.cac.washington.edu (Chuck Pliske)
  109. Subject: Re: Join
  110.  
  111. Bob, (and Bill) I don't have the CI$ discussions archived, but here is the
  112. relateSelection procedure in all its glory:
  113.  
  114. Bill, re:
  115. "In your RelateSelection/built search, do you sort the selection (or
  116. call SELECTION TO ARRAY, then SORT ARRAY) in order to avoid searching
  117. for the same value twice?"
  118.  
  119. No, no sorting, just built searches, for every 250 records of the "input"
  120. file we build a 250 line search command, then execute it.  Note we could
  121. become server compatible by changing the record loop to create sets of 250
  122. records and apply to selection as in the top case, thus avoiding the "next
  123. record" which forces the whole record to be loaded over the net uselessly.
  124.  
  125.   `Procedure RelateSelection
  126.   `it's a good idea to have automatic relations off before running this proc.
  127. gUserCancel:=False  `set up exit test
  128. ON EVENT CALL("CancelTest")
  129. START TRANSACTION
  130. $File1:=File(File($1))  `gets the related records in file 1 for the current
  131.                         `selection of file 2
  132. $File2:=File(File($2))
  133. If (Records in selection($File2>)<257)  `built searches don't like more than 256
  134.   $F1:=$1  `Can't directly use $1 or $2 in Apply to selection
  135.   $F2:=$2
  136.   SEARCH($File1>;$1>=$2>;*)
  137.   APPLY TO SELECTION($File2>;SEARCH($File1>; | $F1>=$F2>;*))
  138.   SEARCH($File1>)
  139. Else 
  140.   CREATE EMPTY SET($file1>;"Related")
  141.   FIRST RECORD($File2>)
  142.   For ($j;1;Records in selection($File2>);250)
  143.     SEARCH($File1>;$1>=$2>;*)
  144.     MESSAGE("Matching "+Filename($File1)+" records to "+Filename($File2)+
  145.             "Records..."+Char(13)+Char(13)+String(Round($j*100/Records in
  146.             selection($File2>);0))+"%")
  147.     $limit:=Lessor (Records in selection($File2>)-Selected record 
  148.                     number($file2>);250)
  149.     For ($i;1;$limit)
  150.       SEARCH($File1>; | $1>=$2>;*)
  151.       NEXT RECORD($File2>)
  152.     End for 
  153.     SEARCH($File1>)
  154.     CREATE SET($File1>;"Relating")
  155.     UNION("Related";"Relating";"Related")
  156.     If (gUserCancel)
  157.       $i:=Records in selection($File2>)+1
  158.     End if 
  159.   End for 
  160.   USE SET("Related")
  161.   CLEAR SET("Related")
  162.   CLEAR SET("Relating")
  163. End if 
  164. CANCEL TRANSACTION
  165. ON EVENT CALL("")
  166.